/*
 *              Copyright (C) 2011 The MusicMod Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *            http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.musicmod.plugin.socialize.twitter;

import oauth.signpost.OAuth;
import oauth.signpost.OAuthConsumer;
import oauth.signpost.OAuthProvider;
import oauth.signpost.commonshttp.CommonsHttpOAuthConsumer;
import oauth.signpost.commonshttp.CommonsHttpOAuthProvider;

import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceScreen;
import android.preference.Preference.OnPreferenceClickListener;
import android.util.Log;
import android.widget.Toast;

public class PreferencesActivity extends PreferenceActivity {

	private Handler mHandler;

	private OAuthConsumer mConsumer;
	private OAuthProvider mProvider;
	private ProgressDialog mSpinner;

	private String verifier;
	private String access_token;
	private String token_secret;

	Preference authorize;
	Preference sign_out;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		addPreferencesFromResource(R.xml.preferences);

		mSpinner = new ProgressDialog(this);
		mSpinner.setMessage(getString(R.string.processing));
		mSpinner.setCancelable(false);

		mHandler = new Handler() {
			public void handleMessage(Message msg) {
				switch (msg.what) {
				case Constants.PROCESS_START:
					mSpinner.show();
					break;
				case Constants.PROCESS_STOP:
					mSpinner.dismiss();
					break;
				case Constants.CREDENTIALS_SAVED:
					authorize.setTitle(R.string.reauthorize);
					authorize.setSummary(R.string.reauthorize_summary);
					sign_out.setEnabled(true);
					break;
				}
			}
		};

		PreferenceScreen screen = this.getPreferenceScreen();
		authorize = (Preference) screen.findPreference(Constants.KEY_AUTHORIZE);
		sign_out = (Preference) screen.findPreference(Constants.KEY_SIGN_OUT);

		authorize.setOnPreferenceClickListener(new OnPreferenceClickListener() {
			public boolean onPreferenceClick(Preference preference) {

				if (!userCredentialsExists()) {
					Thread thread = new Thread() {
						public void run() {
							gotoAuthorizationPage();
						}
					};
					thread.start();
				} else {
					confirmAuthorize();
				}
				return true;
			}
		});

		sign_out.setOnPreferenceClickListener(new OnPreferenceClickListener() {
			public boolean onPreferenceClick(Preference preference) {
				if (userCredentialsExists()) {
					confirmSignOut();
				}
				return true;
			}
		});
	}

	@Override
	protected void onResume() {
		super.onResume();
		sign_out.setEnabled(userCredentialsExists());
		if (userCredentialsExists()) {
			authorize.setTitle(R.string.reauthorize);
			authorize.setSummary(R.string.reauthorize_summary);
		}
	}

	/*
	 * When we get callback from browser after authentication, get the twits and
	 * Launch ListActivity - SocialFeed to display these twits
	 */
	@Override
	protected void onNewIntent(final Intent intent) {
		super.onNewIntent(intent);

		Thread thread = new Thread() {
			public void run() {
				try {
					saveAccessToken(intent);
				} catch (final Exception e) {
					Toast.makeText(PreferencesActivity.this,
							R.string.error_occurred, Toast.LENGTH_SHORT);
					e.printStackTrace();
				}
			}
		};
		thread.start();

	}

	/*
	 * Get authorization url according social service selected
	 * 
	 * @param socialId
	 * 
	 * @return
	 * 
	 * @throws Exception
	 */
	private String getAuthorizationUrl() throws Exception {

		mHandler.sendEmptyMessage(Constants.PROCESS_START);

		mConsumer = new CommonsHttpOAuthConsumer(Constants.CONSUMER_KEY,
				Constants.CONSUMER_SECRET);
		mProvider = new CommonsHttpOAuthProvider(
				Constants.REQUEST_TOKEN_ENDPOINT,
				Constants.ACCESS_TOKEN_ENDPOINT, Constants.AUTHORIZATION_URL);
		mProvider.setOAuth10a(true);

		final String authUrl = mProvider.retrieveRequestToken(mConsumer,
				Constants.CALLBACK_URL);

		mHandler.sendEmptyMessage(Constants.PROCESS_STOP);

		return authUrl;
	}

	private void gotoAuthorizationPage() {
		String authUrl = null;
		try {
			authUrl = getAuthorizationUrl();
		} catch (Exception e) {
			Toast.makeText(PreferencesActivity.this, R.string.error_occurred,
					Toast.LENGTH_SHORT);
			e.printStackTrace();
		}
		if (authUrl != null) {
			Intent intent = new Intent(PreferencesActivity.this,
					AuthorizationActivity.class);
			intent.putExtra("authUrl", authUrl);
			startActivity(intent);
		}
	}

	private void confirmAuthorize() {
		new AlertDialog.Builder(this)
				.setIcon(android.R.drawable.ic_dialog_alert)
				.setTitle(R.string.reauthorize)
				.setMessage(R.string.reauthorize_message)
				.setPositiveButton(R.string.reauthorize,
						new DialogInterface.OnClickListener() {
							public void onClick(DialogInterface di, int i) {
								Thread thread = new Thread() {
									public void run() {
										gotoAuthorizationPage();
									}
								};
								thread.start();
							}
						})
				.setNegativeButton(R.string.cancel,
						new DialogInterface.OnClickListener() {
							public void onClick(DialogInterface di, int i) {
							}
						}).show();
	}

	private void confirmSignOut() {
		new AlertDialog.Builder(this)
				.setIcon(android.R.drawable.ic_dialog_alert)
				.setTitle(R.string.sign_out)
				.setMessage(R.string.sign_out_message)
				.setPositiveButton(R.string.sign_out,
						new DialogInterface.OnClickListener() {
							public void onClick(DialogInterface di, int i) {
								SharedPrefsUtils.setStringPreference(
										PreferencesActivity.this,
										Constants.KEY_ACCESS_TOKEN,
										Constants.DEFAULT_TOKEN_SECRET);
								SharedPrefsUtils.setStringPreference(
										PreferencesActivity.this,
										Constants.KEY_TOKEN_SECRET,
										Constants.DEFAULT_TOKEN_SECRET);
								sign_out.setEnabled(userCredentialsExists());
								if (!userCredentialsExists()) {
									authorize.setTitle(R.string.authorize);
									authorize
											.setSummary(R.string.authorize_summary);
								}
							}
						})
				.setNegativeButton(R.string.cancel,
						new DialogInterface.OnClickListener() {
							public void onClick(DialogInterface di, int i) {
							}
						}).show();
	}

	private boolean userCredentialsExists() {
		if (SharedPrefsUtils.getStringPreference(getApplicationContext(),
				Constants.KEY_ACCESS_TOKEN, Constants.DEFAULT_ACCESS_TOKEN)
				.equals(Constants.DEFAULT_ACCESS_TOKEN)
				|| SharedPrefsUtils.getStringPreference(
						getApplicationContext(), Constants.KEY_TOKEN_SECRET,
						Constants.DEFAULT_TOKEN_SECRET).equals(
						Constants.DEFAULT_TOKEN_SECRET)) {
			return false;
		} else {
			return true;
		}
	}

	/*
	 * Get access token from verifier received in callback URL
	 * 
	 * @param intent
	 * 
	 * @throws Exception
	 */
	private void saveAccessToken(final Intent intent) throws Exception {

		mHandler.sendEmptyMessage(Constants.PROCESS_START);

		final Uri uri = intent.getData();
		if ((uri != null) && uri.toString().startsWith(Constants.CALLBACK_URL)) {
			verifier = uri.getQueryParameter(OAuth.OAUTH_VERIFIER);

			mProvider.setOAuth10a(true);
			mProvider.retrieveAccessToken(mConsumer, verifier);

			access_token = mConsumer.getToken();
			token_secret = mConsumer.getTokenSecret();

			Log.d(Constants.LOG_TAG, "Access token: " + access_token);
			Log.d(Constants.LOG_TAG, "Token secret: " + token_secret);

			SharedPrefsUtils.setStringPreference(this,
					Constants.KEY_ACCESS_TOKEN, access_token);
			SharedPrefsUtils.setStringPreference(this,
					Constants.KEY_TOKEN_SECRET, token_secret);

			mHandler.sendEmptyMessage(Constants.PROCESS_STOP);
			mHandler.sendEmptyMessage(Constants.CREDENTIALS_SAVED);
		}

	}
}